﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using VH6I_B4.ProductParsing;
using VH6I_B4.BronBestandReaders;
using VH6I_B4.Datawarehouse;

namespace VH6I_B4.BronBestandReaders
{
    class XmlReader : ABronBestandReader
    {
        private string _supermarket;
        private string[] _prevRow;
        private ProductParser _productParser;

        public XmlReader(DatawarehouseApi dwh)
            : base(dwh)
        {
        }

        public override void read()
        {
            // Open het XML bestand
            using (XmlTextReader xmlReader = new XmlTextReader(@"C:\Users\rein\Dropbox\B4\Proftaak\Bronbestanden\KoffieDiversenBestand.xml"))
            {
                xmlReader.WhitespaceHandling = WhitespaceHandling.None;

                while (xmlReader.Read())
                {
                    if (xmlReader.NodeType.Equals(XmlNodeType.Element))
                    {
                        if (xmlReader.LocalName.Equals("Worksheet") && xmlReader.GetAttribute("ss:Name").Equals("Sheet1"))
                        {
                            parseWorksheet(xmlReader);
                        }
                    }
                }
            }
        }

        private void parseWorksheet(XmlTextReader xmlReader)
        {
            while (xmlReader.Read())
            {
                if (xmlReader.NodeType.Equals(XmlNodeType.Element) && xmlReader.LocalName.Equals("Row"))
                {
                    // Verkrijg de data uit de rij
                    string[] currentRow = parseRow(xmlReader);

                    // Is er data aanwezig in de kolom met product namen (index 1) ?
                    // en is er een supermarkt gevonden? (geld alleen voor de eerste regels)
                    if (!currentRow[1].Equals(string.Empty) && _supermarket != null)
                    {
                        // Ja: Het is een rij met een product,
                        // Is dit product een barcode?
                        Dictionary<ProductLevel, string> parsedProduct = _productParser.Parse(currentRow[1]);
                        if (parsedProduct.ContainsKey(ProductLevel.BARCODE))
                        {
                            // Ja: Dit is een barcode

                            // ======================
                            // % Volume any Promotion
                            // ======================
                            // 2007
                            _dwh.SaveFact(FactType.VOLUME_ANY_PROMOTION, parsedProduct, _supermarket, 2007, 1, strToDouble(currentRow[2]));
                            _dwh.SaveFact(FactType.VOLUME_ANY_PROMOTION, parsedProduct, _supermarket, 2007, 2, strToDouble(currentRow[3]));
                            _dwh.SaveFact(FactType.VOLUME_ANY_PROMOTION, parsedProduct, _supermarket, 2007, 3, strToDouble(currentRow[4]));
                            _dwh.SaveFact(FactType.VOLUME_ANY_PROMOTION, parsedProduct, _supermarket, 2007, 4, strToDouble(currentRow[5]));
                            // 2008
                            _dwh.SaveFact(FactType.VOLUME_ANY_PROMOTION, parsedProduct, _supermarket, 2008, 1, strToDouble(currentRow[6]));
                            _dwh.SaveFact(FactType.VOLUME_ANY_PROMOTION, parsedProduct, _supermarket, 2008, 2, strToDouble(currentRow[7]));
                            _dwh.SaveFact(FactType.VOLUME_ANY_PROMOTION, parsedProduct, _supermarket, 2008, 3, strToDouble(currentRow[8]));
                            _dwh.SaveFact(FactType.VOLUME_ANY_PROMOTION, parsedProduct, _supermarket, 2008, 4, strToDouble(currentRow[9]));
                            // 2009
                            _dwh.SaveFact(FactType.VOLUME_ANY_PROMOTION, parsedProduct, _supermarket, 2009, 1, strToDouble(currentRow[10]));
                            _dwh.SaveFact(FactType.VOLUME_ANY_PROMOTION, parsedProduct, _supermarket, 2009, 2, strToDouble(currentRow[11]));

                            // ================
                            // % Stores selling
                            // ================
                            // 2007
                            _dwh.SaveFact(FactType.STORES_SELLING, parsedProduct, _supermarket, 2007, 1, strToDouble(currentRow[12]));
                            _dwh.SaveFact(FactType.STORES_SELLING, parsedProduct, _supermarket, 2007, 2, strToDouble(currentRow[13]));
                            _dwh.SaveFact(FactType.STORES_SELLING, parsedProduct, _supermarket, 2007, 3, strToDouble(currentRow[14]));
                            _dwh.SaveFact(FactType.STORES_SELLING, parsedProduct, _supermarket, 2007, 4, strToDouble(currentRow[15]));
                            // 2008
                            _dwh.SaveFact(FactType.STORES_SELLING, parsedProduct, _supermarket, 2008, 1, strToDouble(currentRow[16]));
                            _dwh.SaveFact(FactType.STORES_SELLING, parsedProduct, _supermarket, 2008, 2, strToDouble(currentRow[17]));
                            _dwh.SaveFact(FactType.STORES_SELLING, parsedProduct, _supermarket, 2008, 3, strToDouble(currentRow[18]));
                            _dwh.SaveFact(FactType.STORES_SELLING, parsedProduct, _supermarket, 2008, 4, strToDouble(currentRow[19]));
                            // 2009
                            _dwh.SaveFact(FactType.STORES_SELLING, parsedProduct, _supermarket, 2009, 1, strToDouble(currentRow[20]));
                            _dwh.SaveFact(FactType.STORES_SELLING, parsedProduct, _supermarket, 2009, 2, strToDouble(currentRow[21]));

                            // =======================
                            // % Weighted distribution
                            // =======================
                            // 2007
                            _dwh.SaveFact(FactType.WEIGHTED_DISTRIBUTION, parsedProduct, _supermarket, 2007, 1, strToDouble(currentRow[22]));
                            _dwh.SaveFact(FactType.WEIGHTED_DISTRIBUTION, parsedProduct, _supermarket, 2007, 2, strToDouble(currentRow[23]));
                            _dwh.SaveFact(FactType.WEIGHTED_DISTRIBUTION, parsedProduct, _supermarket, 2007, 3, strToDouble(currentRow[24]));
                            _dwh.SaveFact(FactType.WEIGHTED_DISTRIBUTION, parsedProduct, _supermarket, 2007, 4, strToDouble(currentRow[25]));
                            // 2008
                            _dwh.SaveFact(FactType.WEIGHTED_DISTRIBUTION, parsedProduct, _supermarket, 2008, 1, strToDouble(currentRow[26]));
                            _dwh.SaveFact(FactType.WEIGHTED_DISTRIBUTION, parsedProduct, _supermarket, 2008, 2, strToDouble(currentRow[27]));
                            _dwh.SaveFact(FactType.WEIGHTED_DISTRIBUTION, parsedProduct, _supermarket, 2008, 3, strToDouble(currentRow[28]));
                            _dwh.SaveFact(FactType.WEIGHTED_DISTRIBUTION, parsedProduct, _supermarket, 2008, 4, strToDouble(currentRow[29]));
                            // 2009
                            _dwh.SaveFact(FactType.WEIGHTED_DISTRIBUTION, parsedProduct, _supermarket, 2009, 1, strToDouble(currentRow[30]));
                            _dwh.SaveFact(FactType.WEIGHTED_DISTRIBUTION, parsedProduct, _supermarket, 2009, 2, strToDouble(currentRow[31]));
                        }
                    }

                    // Is het product gelijk aan de categorie koffie?
                    if (currentRow[1].Equals("CATEGORY - KOFFIE"))
                    {
                        // Ja: In de vorige rij zat de naam van een supermarkt
                        _supermarket = _prevRow[1];
                        _productParser = new ProductParser();
                    }
                    _prevRow = currentRow;
                }
            }
        }

        /// <summary>Parst de inhoud van een Row element.</summary>
        /// <param name="xmlReader">
        /// De XmlTextReader waaruit gelezen wordt.
        /// Deze methode verwacht dat de XmlTextReader
        /// gepositioneerd is op een Row element.
        /// </param>
        /// <returns>
        /// Een array van strings met inhoud van de cellen.
        /// </returns>
        private string[] parseRow(XmlTextReader xmlReader)
        {
            // Maak een lege array voor de cell data
            string[] cellData = new string[32];
            int cellCounter = -1;

            // Maak alle cellen leeg
            for (int i = 0; i < cellData.Length; i++)
            {
                cellData[i] = string.Empty;
            }

            // Lees de data uit de cellen
            while (xmlReader.Read())
            {
                // Zijn we bij het einde van en rij ? </Row>
                if (xmlReader.NodeType.Equals(XmlNodeType.EndElement) && xmlReader.LocalName.Equals("Row"))
                {
                    // Ja: Breek de loop
                    break;
                }
                // Is dit een Cell element? <Cell>...</Cell> of <Cell/>
                else if (xmlReader.NodeType.Equals(XmlNodeType.Element) && xmlReader.LocalName.Equals("Cell"))
                {
                    // Is er voor deze cell een index?
                    string index = xmlReader.GetAttribute("ss:Index");
                    if (index != null)
                    {
                        // Ja: Stel de counter in op de index
                        cellCounter = Int16.Parse(index) - 1;
                    }
                    else
                    {
                        // Nee: Hoog de counter op
                        cellCounter++;
                    }
                }
                // Is dit een Data element? <Data>..</Data>
                else if (xmlReader.NodeType.Equals(XmlNodeType.Element) && xmlReader.LocalName.Equals("Data"))
                {
                    // Ja: Haal de inhoud er uit en stop dat in de array
                    // op de plek aangegeven door cellCounter
                    string cellContents = xmlReader.ReadElementContentAsString();
                    cellData[cellCounter] = cellContents.Trim();
                }
            }

            return cellData;
        }

        private void PrintLabels(Dictionary<ProductLevel, string> parsedProduct)
        {
            if (!string.IsNullOrEmpty(_supermarket))
                System.Diagnostics.Debug.WriteLine("[SUPERMARKET]\t" + _supermarket);

            if (parsedProduct.ContainsKey(ProductLevel.MAJOR_BRAND))
                System.Diagnostics.Debug.WriteLine("[MAJOR.BRAND]\t" + parsedProduct[ProductLevel.MAJOR_BRAND]);

            if (parsedProduct.ContainsKey(ProductLevel.APPARAAT))
                System.Diagnostics.Debug.WriteLine("[APPARAAT]\t\t" + parsedProduct[ProductLevel.APPARAAT]);

            if (parsedProduct.ContainsKey(ProductLevel.TYPE))
                System.Diagnostics.Debug.WriteLine("[TYPE]\t\t\t" + parsedProduct[ProductLevel.TYPE]);

            if (parsedProduct.ContainsKey(ProductLevel.BELEVING))
                System.Diagnostics.Debug.WriteLine("[BELEVING]\t\t" + parsedProduct[ProductLevel.BELEVING]);

            if (parsedProduct.ContainsKey(ProductLevel.SOORT))
                System.Diagnostics.Debug.WriteLine("[SOORT]\t\t\t" + parsedProduct[ProductLevel.SOORT]);

            if (parsedProduct.ContainsKey(ProductLevel.FORMAAT))
                System.Diagnostics.Debug.WriteLine("[FORMAAT]\t\t" + parsedProduct[ProductLevel.FORMAAT]);

            if (parsedProduct.ContainsKey(ProductLevel.SMAAK))
                System.Diagnostics.Debug.WriteLine("[SMAAK]\t\t\t" + parsedProduct[ProductLevel.SMAAK]);

            if (parsedProduct.ContainsKey(ProductLevel.BARCODE))
                System.Diagnostics.Debug.WriteLine("[BARCODE]\t\t" + parsedProduct[ProductLevel.BARCODE] + Environment.NewLine);
        }
    }
}
